/*
 * Copyright 2014 http://Bither.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wufun.overseas.utils;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.Log;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

public class NativeUtil {
    private static int DEFAULT_QUALITY = 95;
    public static long DEFAULT_LIMIT_SIZE_UPPER = (long) (0.3 * 1024 * 1024);//300KB

    public static void compressImage(final String src, final String destPath, final int quality, final boolean optim, final NativeCompressListener l) {
//        new Thread(new Runnable() {
//            public void run() {
        try {
//            Logger.log("NativeUtil","compressImage","-->start");
            File file = new File(destPath);
            if (!file.getParentFile().exists()) file.getParentFile().mkdirs();

            long size = 0;
            size = getFileSize(new File(src));
            if (size < DEFAULT_LIMIT_SIZE_UPPER) {
//                Logger.log("Na  tiveUtil","compressImage","-->smaller");
                copyFile(src, destPath);
                if (l != null) l.onSuccess(src);
            } else {
//                Logger.log("NativeUtil","compressImage","-->need compress");
//                        Bitmap bit = BitmapFactory.decodeFile(src);
                Bitmap bit = null;

                //handle oom error
                BitmapFactory.Options opts = new BitmapFactory.Options();
                opts.inDither = false;
                opts.inPurgeable = true;//设置图片可以被回收，创建Bitmap用于存储Pixel的内存空间在系统内存不足时可以被回收
                opts.inInputShareable = true;//设置解码位图的尺寸信息
                opts.inTempStorage = new byte[100 * 1024];//100KB
                opts.inJustDecodeBounds = false;
                opts.inPreferredConfig = Config.RGB_565;//每个像素占用2byte内存（16位）
                File bitF = new File(src);
                FileInputStream fs = null;
                try {
//                    Logger.log("NativeUtil","compressImage","-->get bitmap");
                    fs = new FileInputStream(bitF);
                    if (fs != null)
                        bit = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, opts);
//                    Logger.log("NativeUtil","compressImage","-->get bitmap finished");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (fs != null) {
                        fs.close();
                    }
                }

                if (bit == null) {
//                    Logger.log("NativeUtil","compressImage","-->bitmap is null");
                    return;
                }
//                Logger.log("NativeUtil","compressImage","-->do native compress");
                NativeUtil.compressBitmap(bit, quality, destPath, optim);
//                Logger.log("NativeUtil","compressImage","-->do native compress finished");


                if (!bit.isRecycled()) {
                    bit.recycle();//回收图片所占的内存        
                    System.gc();//提醒系统及时回收
//                    Logger.log("NativeUtil","compressImage","-->compress finished, notify gc");
                }

                if (l != null) l.onSuccess(src);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (l != null) l.onFailed(src);
        }

//            }
//        }).start();
    }

    /**
     * copy a single file
     *
     * @param oldPath String src file path. eg：c:/fqf.txt
     * @param newPath String dest file path. eg：f:/fqf.txt
     * @return boolean
     */
    public static void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                int length;
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字节数 文件大小
                    System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();

        }

    }

    /**
     * 复制整个文件夹内容
     *
     * @param oldPath String 原文件路径 如：c:/fqf
     * @param newPath String 复制后路径 如：f:/fqf/ff
     * @return boolean
     */
    public static void copyFolder(String oldPath, String newPath) {

        try {
            (new File(newPath)).mkdirs(); //create dir if not exist.
            File a = new File(oldPath);
            String[] file = a.list();
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file[i]);
                } else {
                    temp = new File(oldPath + File.separator + file[i]);
                }

                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = new FileOutputStream(newPath + "/" +
                            (temp.getName()).toString());
                    byte[] b = new byte[1024 * 5];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                if (temp.isDirectory()) {//sub dir
                    copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
                }
            }
        } catch (Exception e) {
            System.out.println("fail to copy all files of dir.");
            e.printStackTrace();
        }
    }

    public interface NativeCompressListener {
        void onSuccess(String src);

        void onFailed(String src);
    }

    public static void compressBitmap(Bitmap bit, String fileName, boolean optimize) {
        compressBitmap(bit, DEFAULT_QUALITY, fileName, optimize);
    }

    public static void compressBitmap(Bitmap bit, int quality, String fileName, boolean optimize) {
        Log.d("native", "compress of native");

        Bitmap result = null;

        result = Bitmap.createBitmap(bit.getWidth() / 3, bit.getHeight() / 3, Config.ARGB_8888);//  reduce 3 time
        Canvas canvas = new Canvas(result);
        Rect rect = new Rect(0, 0, bit.getWidth(), bit.getHeight());// original
        rect = new Rect(0, 0, bit.getWidth() / 3, bit.getHeight() / 3);// reduce 3 time
        canvas.drawBitmap(bit, null, rect, null);
        saveBitmap(result, quality, fileName, optimize);
        result.recycle();
    }

    public static long getFileSize(File file) throws Exception {
        long size = 0;
        if (file.exists()) {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                size = fis.available();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    fis.close();
                }
            }
        } else {
            file.createNewFile();
        }
        return size;
    }

    private static void saveBitmap(Bitmap bit, int quality, String fileName, boolean optimize) {
        compressBitmap(bit, bit.getWidth(), bit.getHeight(), quality, fileName.getBytes(), optimize);
    }

    private static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes, boolean optimize);

    static {
        System.loadLibrary("jpegbither");
        System.loadLibrary("bitherjni");
    }

}
